

import java.io.IOException;

import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.*;

public class HelicopterCanvas extends GameCanvas implements Runnable, HeliChangeListener, HeliListener, MissileChangeListener {

    private volatile boolean m_isFlying;
    private HelicopterSprite m_helicopter;
    private TiledLayer m_Background;
    private LayerManager m_LayerManager;
    private HelicopterSprite m_helicopter2;
    private MissileSprite m_missile;
    private MissileSprite m_missile2;
    
    private int m_NetKeyStates = 0;
    
    private NetworkPlayer m_Player;

    public HelicopterCanvas(NetworkPlayer player) throws IOException {
        super(true);

        m_Player = player;
        m_Player.startListen(this);
        m_helicopter = createHelicopter(1);
        m_helicopter.setSpeedListener(this);
        
        m_helicopter.setPosition(20, 24);
        m_missile = createMissile(1);
        m_missile.setPosition(20, 24);
        m_missile.setMissileListener(this);
        
        m_missile2 = createMissile(2);
        m_missile2.setPosition(20, 24);
        m_helicopter2 = createHelicopter(2);
        //m_helicopter2.setPosition (150,144);
        m_helicopter2.setPosition (20,24);
        m_Background = createBoard();
        m_LayerManager = new LayerManager();
        m_LayerManager.append(m_helicopter);
        m_LayerManager.append(m_helicopter2);
        m_LayerManager.append(m_missile);
        m_LayerManager.append(m_missile2);
        m_LayerManager.append(m_Background);
        
        
    }

    private HelicopterSprite createHelicopter(int nr) throws IOException {
        Image image;
        if(nr == 1){
            image = Image.createImage("/helicopterpeq.png");
            return new HelicopterSprite(image, 35, 35);
        
        } else {
            image = Image.createImage("/helicopterpeq2.png");
            return new HelicopterSprite(image, 35, 35);
        }
    }
    
    private MissileSprite createMissile(int nr) throws IOException {
        Image image;
        MissileSprite m = null;
	  if(nr == 1) {
		  image = Image.createImage("/bluemissileseqpeq2.png");
		  m = new MissileSprite(image, 30, 40);
	  } else if (nr == 2) {
		  image = Image.createImage("/redmissileseqpeq2.png");
		  m = new MissileSprite(image, 30, 40);
			
	  }
	  return m;
    }
    
    private TiledLayer createBoard() throws IOException {
        Image image = Image.createImage("/topview_tiles.png");
        TiledLayer tiledLayer = new TiledLayer(15, 20, image, 16, 16);
        int mapWidth = 15;
        int mapHeight = 18;
        int[][] map = {
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 61, 64, 64, 64, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 48, 10, 16,  8, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 48, 16,  9, 16, 46, 64, 64, 64, 60, 0, 0, 0, 0, 0},
            {0, 48, 11, 30, 25, 25, 25, 28, 10, 47, 0, 0, 0, 0, 0},
            {0, 63, 31, 31, 31, 32,  9, 26,  9, 47, 0, 0, 0, 0, 0},
            {0,  0,  0,  0,  0, 48, 16, 26 ,16, 47, 0, 0, 0, 0, 0},
            {0,  0,  0,  0,  0, 63, 31, 41, 31, 62, 0, 0, 0, 0, 0},
            {0,  0,  0,  0,  0,  0,  0, 42, 0, 0, 0, 0, 0, 0, 0},
            {0,  0,  0,  0,  0,  0,  0, 42, 0, 0, 0, 0, 0, 0, 0},
            {0,  0,  0,  0,  0,  0,  0, 42, 0, 0, 0, 0, 0, 0, 0},
            {0,  0,  0,  0,  0, 61, 64, 43, 64, 60, 0, 0, 0, 0, 0},
            {0,  0,  0,  0,  0, 48, 22, 36, 21, 47, 0, 0, 0, 0, 0},
            {0,  0,  0,  0,  0, 48,  7,  2,  5, 47, 0, 0, 0, 0, 0},
            {0,  0,  0,  0,  0, 48, 24,  6, 23, 47, 0, 0, 0, 0, 0},
            {0,  0,  0,  0,  0, 63, 31,  31, 31, 62, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
        };

        for (int i = 0; i < mapWidth; i++) {
            for (int j = 0; j < mapHeight; j++) {
                tiledLayer.setCell(i, j, map[j][i]);
            }

        }

        return tiledLayer;
    }

    public void start() {
        m_isFlying = true;
        Thread t = new Thread(this);
        t.start();
    }

    public void run() {
        Graphics g = getGraphics();

        int FlightSpeed = 30;

        while (m_isFlying) {
            long start = System.currentTimeMillis();
            
            //collision();
            input();
            render(g);

            long end = System.currentTimeMillis();
            int duration = (int) (end - start);
            gameOver(g);
	      outOfDisplay();
            
            if (duration < FlightSpeed) {
                try {
                    Thread.sleep(FlightSpeed - duration);
                    if(m_missile.isShoot()){
                        m_missile.forward(5);
                    }
                    if(m_missile2.isShoot()){
                        m_missile2.forward(5);
                    }
                    
                } catch (InterruptedException ie) {
                    stopHelicopter();
                }
            }
        }
    }
    

     private void outOfDisplay(){
        int width = getWidth();
        int height = getHeight();
        if(m_helicopter.getX()> width){
            m_helicopter.setPosition(0, m_helicopter.getY());
        } else if(m_helicopter.getX()< 0){
            m_helicopter.setPosition(width, m_helicopter.getY()); 
        } else if(m_helicopter.getY()> height){
            m_helicopter.setPosition(m_helicopter.getX(), 0);
        } else if(m_helicopter.getY()< 0){
            m_helicopter.setPosition(m_helicopter.getX(), height);
        }  
        if(m_missile.getX()> width){
            m_missile.setPosition(0, m_missile.getY());
        } else if(m_missile.getX()< 0){
            m_missile.setPosition(width, m_missile.getY()); 
        } else if(m_missile.getY()> height){
            m_missile.setPosition(m_missile.getX(), 0);
        } else if(m_missile.getY()< 0){
            m_missile.setPosition(m_missile.getX(), height);
        }
        if(m_helicopter2.getX()> width){
            m_helicopter2.setPosition(0, m_helicopter2.getY());
        } else if(m_helicopter2.getX()< 0){
            m_helicopter2.setPosition(width, m_helicopter2.getY()); 
        } else if(m_helicopter2.getY()> height){
            m_helicopter2.setPosition(m_helicopter2.getX(), 0);
        } else if(m_helicopter2.getY()< 0){
            m_helicopter2.setPosition(m_helicopter2.getX(), height);
        }
         
        if(m_missile2.getX()> width){
            m_missile2.setPosition(0, m_missile2.getY());
        } else if(m_missile2.getX()< 0){
            m_missile2.setPosition(width, m_missile2.getY()); 
        } else if(m_missile2.getY()> height){
            m_missile2.setPosition(m_missile2.getX(), 0);
        } else if(m_missile2.getY()< 0){
            m_missile2.setPosition(m_missile2.getX(), height);
        }
    }
    
    
    /*private void collision() {
        if (m_helicopter.collidesWith(m_helicopter2, true)) {
        
            stopHelicopter();
            
        } else if (m_helicopter2.collidesWith(m_missile, true)) {
            stopHelicopter();
        } else if(m_missile.collidesWith(m_missile2, true)){
            restoreMissile(m_helicopter, m_missile);
            restoreMissile(m_helicopter2, m_missile2);
        }
    }*/
    private void restoreMissile(HelicopterSprite h, MissileSprite m){
        int x = h.getX();
        int y = h.getY();
        m.setPosition(x, y);
        
    
    }
    private void input() {
        int keyStates = getKeyStates();
        //process own key-states
        processInput(keyStates, m_missile, m_helicopter, m_helicopter2);
        //process net-players moves
        processInput(m_NetKeyStates, m_missile2, m_helicopter2, m_helicopter);

    }

	private void processInput(int keyStates, MissileSprite missile, HelicopterSprite heli, HelicopterSprite otherHeli){
		int speed = HelicopterSprite.STOP;
		int missileTurn = MissileSprite.NOT_TURNING;
		
		if ((keyStates & LEFT_PRESSED) != 0) {
			heli.turn(-1);
            if(!missile.isShoot()){
                missile.turn(-1);
            }
          //  m_helicopter2.turn(-1);
        } else if ((keyStates & RIGHT_PRESSED) != 0) {
        	heli.turn(1);
        	
            if(!missile.isShoot()){
                missile.turn(1);
            }
            
           // m_helicopter2.turn(1);
        } else if ((keyStates & UP_PRESSED) != 0) {
        	heli.forward(5);
        	speed = HelicopterSprite.FORWARD;
            if(!missile.isShoot()){
                missile.forward(5);
            }
                // m_helicopter2.forward(3);
        } else if ((keyStates & DOWN_PRESSED) != 0) {
        	heli.forward(-1);
        	speed = HelicopterSprite.BACKWARD;
            if(!missile.isShoot()){
                missile.forward(-1);
            }
           
          //  m_helicopter2.forward(-1);
        } else if ((keyStates & FIRE_PRESSED) != 0) {
        	
            if(!missile.isShoot()){
                missile.shoot(5, otherHeli);
        
            }
        } else if ((keyStates & GAME_A_PRESSED)!=0){
            if(missile.isShoot()){
            	missileTurn = MissileSprite.TURNING_LEFT;
            	missile.turn(-1);
                
            } 
        } else if ((keyStates & GAME_B_PRESSED)!=0){
            if(missile.isShoot()){
            	missileTurn = MissileSprite.TURNING_RIGHT;
                missile.turn(1);
                
            } 
        }
		
		heli.setSpeed(speed);
		missile.setTurning(missileTurn);
	}

    private void render(Graphics g) {
        int width = getWidth();
        int height = getHeight();

        g.setColor(0x4682B4);
        g.fillRect(0, 0, width, height);

        int x = 0;
        int y = 0;

        m_LayerManager.paint(g, x, y);

        g.setColor(0x000000);
        g.drawRect(x, y, width, height);

        flushGraphics();
    }



    public void gameOver(Graphics g) {
        int w = getWidth();
        int h = getHeight();

        StringBuffer sb = new StringBuffer();
        if (!m_isFlying) {
            
            sb.append("You died,Game Over");
            String s = sb.toString();

            Font font = g.getFont();
            int sw = font.stringWidth(s) + 2;
            int sh = font.getHeight();

            g.setColor(0xffffff);
            g.fillRect((w - sw), (h - sh), sw, sh);
            g.setColor(0x000000);
            g.drawRect((w - sw), (h - sh), sw, sh);
            g.drawString(s, w, h, Graphics.BOTTOM | Graphics.RIGHT);

            flushGraphics();
        }


    }
    public void stopHelicopter() {
        m_isFlying = false;
    }

	public void onHeliBeginsAccelerate(HelicopterSprite heli) {
		try {
			byte forward = 1;
			if (heli.getSpeed() == HelicopterSprite.BACKWARD) forward = 0;
			
			m_Player.moveHelicopter(heli.getDirection(), forward);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

	public void onHeliBeginsTurn(HelicopterSprite heli) {
		// TODO Auto-generated method stub
		
	}

	public void onHeliStopsAccelerate(HelicopterSprite heli) {
		try {
			m_Player.stopHelicopter(heli.getX(), heli.getY());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

	public void onHeliStopsTurn(HelicopterSprite heli) {
		// TODO Auto-generated method stub
		
	}

	public void moveHelicopter(int orientation, boolean isForward) {
		//set the move-bit within the net-keystates
		//correct the orientation
		int deltaDirection = orientation - m_helicopter2.getDirection();
		m_helicopter2.turn(deltaDirection);
		if (!m_missile2.isShoot())m_missile2.turn(deltaDirection);
		m_helicopter2.setDirection(orientation);
		
		if (isForward){
			m_NetKeyStates = 0 | UP_PRESSED;
		}else{
			m_NetKeyStates = 0 | DOWN_PRESSED;
		}
	}

	public void stopHeli(int x, int y) {
		// TODO Auto-generated method stub
		m_NetKeyStates = 0;
		m_helicopter2.setPosition(x, y);
		if (!m_missile2.isShoot()) m_missile2.setPosition(x, y);
		
	}

	public void fireRocket(int dir) {
		int deltaDirection = dir - m_helicopter2.getDirection();
		m_helicopter2.turn(deltaDirection);
		
		int deltaDirectionMissile = dir - m_missile2.getDirection();
		m_missile2.turn(deltaDirectionMissile);
		
		m_NetKeyStates = 0 | FIRE_PRESSED;
		
	}

	public void moveRocket(int x, int y, int dir) {
		
		m_missile2.setPosition(x, y);
		
		System.out.println(dir + "!!!!!!!!!!!!!!!!!!!!!");
		//left
		if (dir == 0) {
			m_NetKeyStates = 0 | GAME_A_PRESSED;
		} else {
			//right
			m_NetKeyStates = 0 | GAME_B_PRESSED;
		}
		processInput(m_NetKeyStates, m_missile2, m_helicopter2, m_helicopter);
	}

	public void stopRocket(int x, int y, int dir) {
		m_missile2.setPosition(x, y);
		
		m_NetKeyStates = 0;
		
		int deltaDirection = dir - m_missile2.getDirection();
		m_missile2.turn(deltaDirection);
	}

	public void onMissileBeginsTurn(MissileSprite m) {
		try {
			System.out.println("HelicopterCanvas.onMissileBeginsTurn()");
			if ( m.getTurning() == MissileSprite.TURNING_LEFT ){
				m_Player.moveRocket(0, m.getX(), m.getY());	
			}else{
				m_Player.moveRocket(1, m.getX(), m.getY());
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public void onMissileFire(MissileSprite m) {
		try {
			m_Player.fireRocket(m.getDirection());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void onMissileStopsTurn(MissileSprite m) {
		System.out.println("HelicopterCanvas.onMissileStopsTurn()");
		try {
			m_Player.stopRocket(m.getDirection(), m.getX(), m.getY());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}

